﻿using System;
using BP.DA;
using BP.En;
using System.Data;

namespace BP.Demo
{
    /// <summary>
    /// 推断报告 属性
    /// </summary>
    public class RptAttr : EntityNoNameAttr
    {
        /// <summary>
        /// 推断报告内容
        /// </summary>
        public const string Docs = "Docs";
    }
    /// <summary>
    /// 推断报告
    /// </summary>
    public class Rpt : EntityMyPK
    {

        #region 构造方法
        /// <summary>
        /// 权限控制
        /// </summary>
        public override UAC HisUAC
        {
            get
            {
                UAC uac = new UAC();
                uac.IsUpdate = true;
                uac.IsInsert = true;
                return uac;
            }
        }
        /// <summary>
        /// 推断报告
        /// </summary>
        public Rpt()
        {
        }
        public Rpt(string no)
        {
            MyPK = no;
            Retrieve();
        }
        /// <summary>
        /// 重写基类方法
        /// </summary>
        public override Map EnMap
        {
            get
            {
                if (_enMap != null)
                    return _enMap;

                Map map = new Map("Demo_Rpt", "推断报告");

                map.AddGroupAttr("基本参数");
                map.AddMyPK();
                map.AddTBString("StockNo", null, "股票编号", true, false, 0, 100, 10, true);
                map.AddTBString("StockName", null, "股票名称", true, true, 0, 300, 100);
                map.AddTBString("IdxNo", null, "执行序号", true, false, 0, 100, 10, true);
                map.AddDDLSysEnum("ExceModel", 0, "模式", true, true, "ExceModel", "@0=单股@1=多线程");
                map.AddTBMoney("Principal", 20, "本金", true, true);
                //公共参数.
                map.AddTBDate("DTFrom", null, "日期从", true, false);
                map.AddTBDate("DTTo", null, "日期到", true, false);
                map.AddTBInt("TradeTimes", 0, "交易次", true, true);//从原始数据自动计算.

                map.AddTBInt("CarWidth", 1, "车宽", true, true);
                map.AddTBInt("NearDays", 4, "最近的天数", true, true);

                map.AddGroupAttr("推断结果");
                map.AddTBInt("ResultAll", 0, "交易次数(日期)总数", true, true);
                map.AddTBInt("ResultTop", 0, "命中高位次数", true, true);
                map.AddTBInt("ResultDown", 0, "命中低位次数", true, true);
                map.AddTBMoney("ResultWin", 0, "纯盈利", true, true);
                map.AddTBMoney("ResultWinRate", 0, "比例", true, true);

                map.AddTBInt("ResultSta0", 0, "完美", true, true);
                map.AddTBInt("ResultSta1", 0, "卖出", true, true);
                map.AddTBInt("ResultSta2", 0, "买入", true, true);
                map.AddTBInt("ResultSta3", 0, "全翻车", true, true);
                map.AddTBInt("Onhand", 0, "库存", true, true);
                map.AddTBString("JNote", null, "预测说明", true, true, 0, 600, 10, true);

                //从表
                map.AddDtl(new RptDtls(), "RptMyPK", "");

                _enMap = map;
                return _enMap;
            }
        }
        #endregion
        /// <summary>
        /// 按照平均数来预测
        /// </summary>
        /// <returns></returns>
        public string DoStockModel1()
        {
            try
            {
                #region 1.数据准备.

                #endregion 1.数据准备.

                #region 2.执行推断.
                //获得范围数据.
                string sql = "SELECT No FROM Demo_Trade WHERE (Name >='" + DTFrom + "' AND Name <='" + DTTo + "') AND StockNo='" + StockNo + "' ORDER BY No ";
                DataTable dataTable = DBAccess.RunSQLReturnTable(sql);
                if (dataTable.Rows.Count == 0) return "err@请检查日期是否错误:从：[" + DTFrom + "] 到:[" + DTTo + "], SQL:" + sql;
                //定义一个集合，为后面所用.
                RptDtls dtls = new RptDtls();
                foreach (DataRow dr in dataTable.Rows)
                {
                    string no = dr[0].ToString();
                    Trade td = new Trade(no); //原始数据.

                    RptDtl jd = new RptDtl();
                    jd.Copy(td); //复制过来采集的数据.
                    jd.RptMyPK = MyPK;
                    jd.TradeNo = td.No;
                    jd.MyPK = td.No + "_" + MyPK; //设置一个主键.
                    jd.Insert();

                    string info = jd.DoStockModel1(this); //执行推断,按照模式1推断.
                    if (info.Contains("err@") == true)
                        continue;

                    dtls.AddEntity(jd);
                }
                #endregion 执行推断.

                #region 3.编写报告.
                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE RptMyPK='" + MyPK + "' AND IsOK=1";
                ResultAll = DBAccess.RunSQLReturnValInt(sql); //总数..

                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE IsTop=1 AND RptMyPK='" + MyPK + "' AND IsOK=1";
                ResultTop = DBAccess.RunSQLReturnValInt(sql); //命中的top数据.

                //命名down数据.
                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE IsDown=1 AND RptMyPK='" + MyPK + "' AND IsOK=1";
                ResultDown = DBAccess.RunSQLReturnValInt(sql); //命中的top数据.

                //结果状态.
                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE ResultSta=0 AND RptMyPK='" + MyPK + "' AND IsOK=1";
                SetValByKey("ResultSta0", DBAccess.RunSQLReturnValInt(sql)); //结果状态.

                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE ResultSta=1 AND RptMyPK='" + MyPK + "' AND IsOK=1";
                SetValByKey("ResultSta1", DBAccess.RunSQLReturnValInt(sql));

                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE ResultSta=2 AND RptMyPK='" + MyPK + "' AND IsOK=1";
                SetValByKey("ResultSta2", DBAccess.RunSQLReturnValInt(sql));

                sql = "SELECT COUNT(*) AS Num FROM Demo_RptDtl WHERE ResultSta=3 AND RptMyPK='" + MyPK + "' AND IsOK=1";
                SetValByKey("ResultSta3", DBAccess.RunSQLReturnValInt(sql));

                Update(); //写入报告.
                #endregion 编写报告.

                #region 4. 按照一直股票投入计算利益.
                if (ExceModel == 0)
                {
                    for (int i = 0; i < dtls.Count; i++)
                    {
                        RptDtl dtl = (RptDtl)dtls[i];
                        dtl.RetrieveFromDBSources();
                        dtl.Outgo = 0;
                        dtl.Income = 0;
                        dtl.ExecNote = "";
                        if (i == 0)
                        {
                            dtl.Income = Principal; //把本金放入里面去.
                            dtl.Update(); //更新到数据库, 因为第一天必须是要买的，没有收入项.
                        }

                        //遇到0，就买入.
                        if (Onhand == 0)
                        {
                            if (dtl.StockSafeDown > dtl.ResultMin)
                            {
                                Onhand = 1;
                                dtl.Outgo = dtl.StockSafeDown; //支出.
                                dtl.ExecNote = "以[" + dtl.StockSafeDown + "]价格购入.";
                                dtl.Win = DBAccess.RunSQLReturnValDecimal("SELECT sum(Income-Outgo) as aa FROM Demo_RptDtl WHERE RptMyPK='" + MyPK + "'", 0, 4);
                                dtl.Update();
                                continue;
                            }
                            continue; //今天没有买到.
                        }
                        //遇到1就卖出.
                        if (Onhand == 1)
                        {
                            if (dtl.StockSafeTop < dtl.ResultMax)
                            {
                                Onhand = 0;
                                dtl.Income = dtl.StockSafeTop; //收入.
                                dtl.ExecNote = "以[" + dtl.StockSafeTop + "]价格卖出.";
                                dtl.Win = DBAccess.RunSQLReturnValDecimal("SELECT sum(Income-Outgo) as aa FROM Demo_RptDtl WHERE RptMyPK='" + MyPK + "'", 0, 4);
                                dtl.Update();
                                continue;
                            }
                            continue; //今天没有买到.
                        }

                        dtl.ExecNote = "今日无事.";
                        dtl.Update();
                    }

                    //计算盈利.
                    decimal win = DBAccess.RunSQLReturnValDecimal("SELECT SUM(Income-Outgo) as aa FROM Demo_RptDtl WHERE RptMyPK='" + MyPK + "'", 0, 4) - Principal;
                    if (Onhand == 1)
                    {
                        //加上上次买入的价格.
                        decimal lastOutGo = DBAccess.RunSQLReturnValDecimal("SELECT Outgo from Demo_RptDtl WHERE RptMyPK='" + MyPK + "' AND  Outgo>0   ORDER BY TradeNo DESC   LIMIT 1", 0, 2);
                        win = win + lastOutGo;
                    }
                    ResultWin = win;
                    ResultWinRate = 0; //如何计算收益率?
                }
                #endregion 4. 按照一直股票投入计算利益.

                string note = "本次预测报告:";
                note += "\t\n 1. 完美预测:" + GetValStrByKey("ResultSta3") + ",卖出天:" + GetValStrByKey("ResultSta1") + ",买入天:" + GetValStrByKey("ResultSta2") + ",翻车天:" + GetValStrByKey("ResultSta3");
                note += "\t\n 2. 参数,车宽:" + CarWidth + ",样本天:[" + NearDays + "]";
                note += "\t\n 3. 库存股票:" + Onhand + "个,纯盈利:" + ResultWin + ",投入的本金是:[" + Principal + "].";
                note += "\t\n 4. 交易次数:" + TradeTimes + ".";
                note += "\t\n     报告日期:" + DataType.CurrentDateTimeCN;

                JNote = note; //说明
                Update();

                return note.Replace("\t\n", "<br/>");
            }
            catch (Exception ex)
            {
                StockState = 2;
                Update();
                return "推断执行失败:" + ex.Message;

            }
        }

        #region 基本属性
        /// <summary>
        /// 执行模式0=单股模式,1=多线程.
        /// </summary>
        public int ExceModel
        {
            get
            {
                return GetValIntByKey("ExceModel");
            }
            set
            {
                SetValByKey("ExceModel", value);
            }
        }
        public string JNote
        {
            get
            {
                return GetValStringByKey("JNote");
            }
            set
            {
                SetValByKey("JNote", value);
            }
        }
        /// <summary>
        /// 编号
        /// </summary>
        public string IdxNo
        {
            get
            {
                return GetValStringByKey("IdxNo");
            }
            set
            {
                SetValByKey("IdxNo", value);
            }
        }
        public string StockNo
        {
            get
            {
                return GetValStringByKey("StockNo");
            }
            set
            {
                SetValByKey("StockNo", value);
            }
        }
        public string StockName
        {
            get
            {
                return GetValStringByKey("StockName");
            }
            set
            {
                SetValByKey("StockName", value);
            }
        }
        public int TradeTimes
        {
            get
            {
                return GetValIntByKey("TradeTimes");
            }
            set
            {
                SetValByKey("TradeTimes", value);
            }
        }

        /// <summary>
        /// 推断状态
        /// </summary>
        public int StockState
        {
            get
            {
                return GetValIntByKey("StockState");
            }
            set
            {
                SetValByKey("StockState", value);
            }
        }
        /// <summary>
        /// 最高值
        /// </summary>
        public string DTFrom
        {
            get
            {
                return GetValStringByKey("DTFrom");
            }
            set
            {
                SetValByKey("DTFrom", value);
            }
        }
        public string DTTo
        {
            get
            {
                return GetValStringByKey("DTTo");
            }
            set
            {
                SetValByKey("DTTo", value);
            }
        }
        public int ResultAll
        {
            get
            {
                return GetValIntByKey("ResultAll");
            }
            set
            {
                SetValByKey("ResultAll", value);
            }
        }
        public int ResultDown
        {
            get
            {
                return GetValIntByKey("ResultDown");
            }
            set
            {
                SetValByKey("ResultDown", value);
            }
        }
        public int ResultTop
        {
            get
            {
                return GetValIntByKey("ResultTop");
            }
            set
            {
                SetValByKey("ResultTop", value);
            }
        }
        /// <summary>
        /// 本金
        /// </summary>
        public decimal Principal
        {
            get
            {
                return GetValDecimalByKey("Principal");
            }
            set
            {
                SetValByKey("Principal", value);
            }
        }

        public decimal ResultWin
        {
            get
            {
                return GetValDecimalByKey("ResultWin");
            }
            set
            {
                SetValByKey("ResultWin", value);
            }
        }
        public decimal ResultWinRate
        {
            get
            {
                return GetValDecimalByKey("ResultWinRate");
            }
            set
            {
                SetValByKey("ResultWinRate", value);
            }
        }


        public int NearDays
        {
            get
            {
                return GetValIntByKey("NearDays");
            }
            set
            {
                SetValByKey("NearDays", value);
            }
        }
        public decimal CarWidth
        {
            get
            {
                return GetValIntByKey("CarWidth");
            }
            set
            {
                SetValByKey("CarWidth", value);
            }
        }
        public int Onhand
        {
            get
            {
                return GetValIntByKey("Onhand");
            }
            set
            {
                SetValByKey("Onhand", value);
            }
        }
        #endregion
    }
    /// <summary>
    /// 推断报告 s
    /// </summary>
    public class Rpts : EntitiesMyPK
    {
        #region 构造函数.
        /// <summary>
        /// 推断报告
        /// </summary>
        public Rpts() { }
        /// <summary>
        /// 得到它的 Entity 
        /// </summary>
        public override Entity GetNewEntity
        {
            get
            {
                return new Rpt();
            }
        }
        #endregion 构造函数.

        #region 为了适应自动翻译成java的需要,把实体转换成List.
        /// <summary>
        /// 转化成 java list,C#不能调用.
        /// </summary>
        /// <returns>List</returns>
        public System.Collections.Generic.IList<Rpt> ToJavaList()
        {
            return (System.Collections.Generic.IList<Rpt>)this;
        }
        /// <summary>
        /// 转化成list
        /// </summary>
        /// <returns>List</returns>
        public System.Collections.Generic.List<Rpt> Tolist()
        {
            System.Collections.Generic.List<Rpt> list = new System.Collections.Generic.List<Rpt>();
            for (int i = 0; i < Count; i++)
            {
                list.Add((Rpt)this[i]);
            }
            return list;
        }
        #endregion 为了适应自动翻译成java的需要,把实体转换成List.
    }
}
